package chat_views

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/websocket"
	"log"
	"rabbit_love/src/model"
	"rabbit_love/src/service/client/utils"
	"rabbit_love/src/service/client/utils/cache"
	"strconv"
	"strings"
	"time"
)

//type RedisMsgQueue struct {
//
//}

func StartClientManager() {
	go Manager.Start()
	go Manager.HeartBeats(TimeDurationHeartBeats)
}

// Start 启动监管器协程
func (manager *ClientManager) Start() {
	for {
		select {
		case conn := <-Manager.Register:

			/*
				连接消息
			*/
			log.Printf("用户已经建立连接，%v", conn.MineId)
			Manager.Users[conn.MineId] = conn
			replyMsg := &ReplyMsg{
				Code:    WSConnSuccess,
				Content: "已连接至服务器",
			}
			marshal, err := json.Marshal(replyMsg)
			if err != nil {
				log.Println("Json Err: ", err)
			}
			if err := conn.Socket.WriteMessage(websocket.TextMessage, marshal); err != nil {
				log.Println("Register Err: ", err)
			}

			/*
				获取Redis中的消息队列
			*/
		case conn := <-Manager.UnRegister:
			if _, ok := Manager.Users[conn.MineId]; ok {
				replyMsg := &ReplyMsg{
					Code:    WSConnDisConnect,
					Content: "连接已断开",
				}
				marshal, err := json.Marshal(replyMsg)
				if err != nil {
					log.Println("Json Err: ", err)
				}
				_ = conn.Socket.WriteMessage(websocket.TextMessage, marshal)
				close(conn.Message)
				_ = conn.Socket.Close()
				delete(Manager.Users, conn.MineId)
			}
		case broadCast := <-Manager.BroadCast:
			log.Printf("%v 用户进行了广播，发送消息给 %v", broadCast.Client.MineId, broadCast.Client.SendId)
			sendID := broadCast.Client.SendId
			message := broadCast.Message
			flag := false // 默认对方不在线

			// MySQL 存入消息表
			var (
				clientDB = utils.ClientDB
			)
			ids := strings.Split(broadCast.Client.MineId, "->")
			fromID, _ := strconv.Atoi(ids[0])
			toID, _ := strconv.Atoi(ids[1])
			data := &model.ChatTable{
				From: int64(fromID),
				To:   int64(toID),
				Read: true,
				Data: message.Msg,
			}
			clientDB.Create(&data)

			// 发送消息
			for id, conn := range Manager.Users {
				if id != sendID {
					continue
				}
				select {
				case conn.Message <- &message:
					flag = true
				default:
					close(conn.Message)
					delete(Manager.Users, conn.MineId)
				}
			}

			if !flag {
				// Redis 缓存未读取的消息
				var ok bool
				ok, _ = cache.RedisMsgDB.HSet(broadCast.Client.MineId, strconv.FormatInt(time.Now().Unix(), 10), broadCast.Message.Msg).Result()
				if ok != true {
					log.Println("StorageRedis Write Err")
				}
				ok, _ = cache.RedisMsgDB.Expire(broadCast.Client.MineId, ExpireMsg).Result()
				if ok != true {
					log.Println("StorageRedis Expire Err")
				}

				_, _ = cache.RedisMsgCountDB.Incr(broadCast.Client.MineId).Result()

			}
		}
	}
}

// HeartBeats 心跳检测机制
func (cm *ClientManager) HeartBeats(nums int64) {
	for {
		time.Sleep(time.Second)
		for _, v := range cm.Users {
			//fmt.Printf("当前时间差%v, 设定时间差%v \n", time.Now().Unix() - v.ProductionTime, nums)
			if time.Now().Unix()-v.ProductionTime >= nums {
				cm.UnRegister <- v
				break
			}
		}
	}
}

//func StorageRedis(broadcast *BroadCast) {
//	var ok bool
//
//	ok, _ = cache.RedisMsgDB.HSet(broadcast.Client.MineId, strconv.FormatInt(time.Now().Unix(), 10), broadcast.Message.Msg).Result()
//	if ok != true {
//		log.Println("StorageRedis Write Err")
//	}
//	ok, _ = cache.RedisMsgDB.Expire(broadcast.Client.MineId, ExpireMsg).Result()
//	if ok != true {
//		log.Println("StorageRedis Expire Err")
//	}
//}
//
//func IncrRedis(mineId string) {
//	_, _ = cache.RedisMsgCountDB.Incr(mineId).Result()
//}

type FindAllMsgStruct struct {
	From  int64
	Count int64
	Msg   []*Msg
}

type Msg struct {
	InformationTime int64
	Msg             string
}

func FindAllMsg(mineId string) []*FindAllMsgStruct {
	var (
		allMsg []*FindAllMsgStruct
	)

	result, _ := cache.RedisMsgCountDB.Keys("*->" + strings.Split(mineId, "->")[0]).Result()
	for _, v := range result {
		countStr, _ := cache.RedisMsgCountDB.Get(v).Result()
		_, _ = cache.RedisMsgCountDB.Del(v).Result()
		count, err := strconv.Atoi(countStr)
		if err != nil {
			log.Println("解析失败")
		}

		if count <= 0 {
			continue
		}

		var thisMsg []*Msg

		msgNoStruct, _ := cache.RedisMsgDB.HGetAll(v).Result()
		for key, val := range msgNoStruct {
			informationTime, _ := strconv.Atoi(key)
			thisMsg = append(thisMsg, &Msg{
				InformationTime: int64(informationTime),
				Msg:             val,
			})
		}

		fromId, _ := strconv.Atoi(strings.Split(v, "->")[0])
		allMsg = append(allMsg, &FindAllMsgStruct{
			From:  int64(fromId),
			Count: int64(count),
			Msg:   thisMsg,
		})
	}
	fmt.Printf("%+v", allMsg)
	return allMsg
}
